/**
 * 如何判断一个属性存不存在
 */

function OBJ() {}
OBJ.prototype.a = "2";

const b = Symbol.for("b");

const obj = {
  a: "1",
  [Symbol(1)]: 3,
  [b]: "22",
  c: "33"
};

// const obj = [];
// Array.prototype.b = "2";
Object.defineProperty(obj, "a", {
  enumerable: false // 不可枚举
});
// const obj = new OBJ();

/**
 * obj.a === undefined
 */
// console.log(obj.a === undefined);

/**
 * Object.keys(obj).includes(a)
 * 这个方法是判断obj的自有属性且可枚举
 */
// console.log(Object.keys(obj).includes("a"));
// console.log(Object.keys(obj));

/**
 * for...in 可枚举包括继承的属性
 */
// console.log(Object.getOwnPropertyDescriptor(Array.prototype, "push"));
/* for (const prop in obj) {
  console.log(prop);
} */

/**
 * in 操作符&Reflect.has() 自身或者继承属性，包括不可枚举、Symbol属性
 */
/* console.log("a" in obj);
console.log(Reflect.has(obj, "toString"));
console.log(Symbol.iterator in []);
console.log(b in obj);
console.log(Reflect.has(obj, b)); */

/**
 * Reflect.ownKeys()返回自身包括不可枚举的属性
 * 是Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))集合
 */
console.log(Reflect.ownKeys(obj));

Reflect.ownKeys(obj).forEach(key => {
  console.log(obj.hasOwnProperty(key));
});

/**
 * Object.prototype.hasOwnProperty()&Object.hasOwn()
 * 对象自身指定属性包括不可枚举，不包括继承
 */
// console.log(obj.hasOwnProperty(Symbol.for("b")));
// console.log(Object.hasOwn(obj, "a"));
// console.log(obj[Symbol.for("b")]);

/**
 * 总结：
 * 1、in 操作符：自有的、继承的、不可枚举、Symbol属性
 * 2、Reflect.has()与in操作符一样
 * 3、Object.hasOwn()与Object.prototype.hasOwnProperty()一样，自有的、非继承的、不可枚举、Symbol属性
 * 4、Object.keys()：自有的、非继承的、可枚举、非Symbol属性
 * 5、for...in：自有的、继承的、可枚举的、非Symbol属性
 * 6、Reflect.ownKeys()：自有的、非继承的、不可枚举的、Symbol属性
 */
